package com.william.jdbcplus.test.config;

import com.william.jdbcplus.core.crud.CrudConfig;
import com.william.jdbcplus.core.crud.IBaseCrud;
import com.william.jdbcplus.core.crud.impl.BaseCrud;
import com.william.jdbcplus.core.dao.IBaseDao;
import com.william.jdbcplus.core.dao.impl.BaseDaoImpl;
import com.william.jdbcplus.core.interceptor.JdkProxyHandler;
import com.william.jdbcplus.core.toolkit.StringUtil;
import com.william.jdbcplus.core.util.JdbcUtil;
import com.william.jdbcplus.test.interceptor.DaoInterceptor;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.integration.redis.util.RedisLockRegistry;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;

public class BeanUtil {

    public static RedisConnectionFactory redisConnectionFactory = initRedisConnectionFactory();

    public static RedisTemplate<String, ?> redisTemplate = initRedisTemplate();

    public static StringRedisTemplate stringRedisTemplate = initStringRedisTemplate();

    public static RedisLockRegistry redisLockRegistry = initRedisLockRegistry();

    public static IBaseDao baseDao = initBaseDao();

    public static PlatformTransactionManager transactionManager = initTransactionManager();

    public static TransactionTemplate transactionTemplate = initTransactionTemplate();

    private static IBaseDao initBaseDao() {
        CrudConfig crudConfig = new CrudConfig(JdbcUtil.getJdbcTemplate(DBUtil.getMysql()), JdbcUtil.getNamedParameterJdbcTemplate(DBUtil.getMysql()), redisTemplate, redisLockRegistry);
        IBaseCrud baseCrud = (IBaseCrud) JdkProxyHandler.bind(new BaseCrud(), new DaoInterceptor());
        IBaseDao baseDao = new BaseDaoImpl(crudConfig, baseCrud);
        return baseDao;
    }

    private static LettuceConnectionFactory initRedisConnectionFactory() {
        // 连接池配置
        GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
        poolConfig.setMaxIdle(8);
        poolConfig.setMinIdle(1);
        poolConfig.setMaxTotal(8);
        poolConfig.setMaxWaitMillis(5000L);
        LettucePoolingClientConfiguration lettucePoolingClientConfiguration = LettucePoolingClientConfiguration.builder().poolConfig(
                poolConfig).build();

        // 单机redis
        RedisStandaloneConfiguration redisConfig = new RedisStandaloneConfiguration();
        redisConfig.setHostName(ConfigUtil.redis_host);
        redisConfig.setPort(ConfigUtil.redis_port);
        if (StringUtil.isNotBlank(ConfigUtil.redis_password)) {
            redisConfig.setPassword(ConfigUtil.redis_password);
        }

        // 哨兵redis
        // RedisSentinelConfiguration redisConfig = new RedisSentinelConfiguration();

        // 集群redis
		/*RedisClusterConfiguration redisConfig = new RedisClusterConfiguration();
		Set<RedisNode> nodeses = new HashSet<>();
		String[] hostses = nodes.split("-");
		for (String h : hostses) {
		    h = h.replaceAll("\\s", "").replaceAll("\n", "");
		    if (!"".equals(h)) {
		        String host = h.split(":")[0];
		        int port = Integer.valueOf(h.split(":")[1]);
		        nodeses.add(new RedisNode(host, port));
		    }
		}
		redisConfig.setClusterNodes(nodeses);
		// 跨集群执行命令时要遵循的最大重定向数量
		redisConfig.setMaxRedirects(3);
		redisConfig.setPassword(password);*/

        return new LettuceConnectionFactory(redisConfig, lettucePoolingClientConfiguration);
    }

    private static RedisTemplate<String, ?> initRedisTemplate() {
        RedisTemplate<String, ?> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        JdkSerializationRedisSerializer jdkSerializationRedisSerializer = new JdkSerializationRedisSerializer();
        redisTemplate.setDefaultSerializer(jdkSerializationRedisSerializer);
        redisTemplate.setKeySerializer(stringRedisSerializer);
        redisTemplate.setValueSerializer(jdkSerializationRedisSerializer);
        redisTemplate.setStringSerializer(stringRedisSerializer);
        redisTemplate.setHashKeySerializer(jdkSerializationRedisSerializer);
        redisTemplate.setHashValueSerializer(jdkSerializationRedisSerializer);
        return redisTemplate;
    }

    private static StringRedisTemplate initStringRedisTemplate() {
        StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
        stringRedisTemplate.setConnectionFactory(redisConnectionFactory);
        return stringRedisTemplate;
    }

    private static RedisLockRegistry initRedisLockRegistry() {
        return new RedisLockRegistry(redisConnectionFactory, "jdbc-plus-lock");
    }

    private static PlatformTransactionManager initTransactionManager() {
        return new DataSourceTransactionManager(DBUtil.getMysql());
    }

    private static TransactionTemplate initTransactionTemplate() {
        return new TransactionTemplate(transactionManager);
    }

}
